/**
 * @Author: jichang
 * @Date: 2024/10/29 13:33:49
 * @LastEditors: jichang
 * @LastEditTime: 2024/10/29 13:33:49
 * Description: 用户状态机
 */

#include "sender.hpp"
#include "withdraw.hpp"
#include "receiver.hpp"
#include "dispatcher.hpp"
#include "simple_msg_queue.hpp"

class interface_machine {
public:
    void done() {
        get_sender().send(messaging::close_queue());
    }

    void run() {
        try {
            while (1) {
                incoming.wait().handle<issue_money>([&](issue_money const& msg) {
                    {
                        std::lock_guard<std::mutex> lock(mtx);
                        std::cout << "Issuing " << msg.amount << std::endl;
                    }
                }).handle<display_insufficient_funds>([&](display_insufficient_funds const& msg) {
                    {
                        std::lock_guard<std::mutex> lock(mtx);
                        std::cout << "Issuing funds" << std::endl;
                    }
                }).handle<display_enter_pin>([&](display_enter_pin const& msg) {
                    {
                        std::lock_guard<std::mutex> lock(mtx);
                        std::cout << "Please enter you PIN(0-9)" << std::endl;
                    }
                }).handle<display_enter_card>([&](display_enter_card const& msg) {
                    {
                        std::lock_guard<std::mutex> lock(mtx);
                        std::cout << "Please enter you card(I)" << std::endl;
                    }
                }).handle<display_balance>([&](display_balance const& msg) {
                    {
                        std::lock_guard<std::mutex> lock(mtx);
                        std::cout << "The balance of your account is " 
                            << msg.amount << std::endl;
                    }
                }).handle<display_withdrawal_options>([&](display_withdrawal_options const& msg) {
                    {
                        std::lock_guard<std::mutex> lock(mtx);
                        std::cout << "Withdraw 50? (w)\n";
                        std::cout << "Display Blance? (b)\n";
                        std::cout << "Cancel? (c)\n"; 
                    }
                }).handle<display_withdrawal_cancelled>([&](display_withdrawal_cancelled const& msg) {
                    {
                        std::lock_guard<std::mutex> lock(mtx);
                        std::cout << "Withdrawal cancelled\n";
                    }
                }).handle<display_pin_incorrect_message>([&](display_pin_incorrect_message const& msg) {
                    {
                        std::lock_guard<std::mutex> lock(mtx);
                        std::cout << "PIN incorrect\n";
                    }
                }).handle<eject_card>([&](eject_card const& msg) {
                    {
                        std::lock_guard<std::mutex> lock(mtx);
                        std::cout << "Ejecting card\n";
                    }
                });
            }
        } catch(messaging::close_queue const&) { }
    }
    messaging::sender get_sender() {
        return incoming;
    }
private:
    messaging::receiver incoming;
    std::mutex mtx;
};